//@author A0101056Y
//Operations class follows Singleton skeleton
//For example, to call executeCommand, declare
//	WriteOperationPtr ptrName = &Operations::get();
//	ptrName->executeCommand(aCommand);

//Operations gets the processed commands from userCommand class and 
//further execute each of the command by calling respective functions. 
//The operations implemented are: 
//1. add an event to the storage
//2. delete an event or many events based on the task IDs
//3. edit an or many event's attributes
//4. display all events
//5. search events by different filters
//6. undo one or many past operations
//7. sort events by time
//8. find help information for operations
//9. change the setting of the TaskExemplar
//10.save the file whenever users feel necessay or exit the program
  

#pragma once

#include <algorithm>
#include "help.h"
#include "Hinter.h"
#include "UserCommand.h"
#include "InternalCommand.h"
#include "EventStorage.h"
#include "ActionList.h"
#include "IndexTranslator.h"
#include "OutputDisplay.h"
#include "SearchEngine.h"
#include "CallDueEvents.h"
#include "HistoryRecord.h"

using namespace SearchConstants;

class Operations {

public: 
	~Operations();
	static Operations& get();
    void initializeOperations();
	void executeCommand(UserCommand& aCommand);
	void executeUndo(UserCommand& aCommand);
	void executeInternal (const InternalCommand& aCommand);
	void updateRepeat();
	void readFromStorage ();
	void setTab (pos_int Num);

private:
	static bool hasRun; 
	Operations ();
	Operations (const Operations&);
	Operations& operator = (const Operations&);

	IndexTranslator _availableData[SIZE_OF_INDEX_TRANSLATOR];
	CurrentTabs _currentTab;
	EventVector* _eventList;   
	MODIFY_STRUCT _myModifyInfo;	
	int _dequeuedID;
	pos_int _toConfig;

	void addEvent (Event anEvent);
	void deleteByNumber (const vector<pos_int> & IDs);
	void deleteByEvent (Event anEvent);
	void modifyEvent (const MODIFY_STRUCT& info);
	void markEvent (const MARK_STRUCT& markInfo); 
	void markEvent (pos_int storageID, MarkFilter newFilter);
	void configStep2 (int index, UserCommand& aCommand); 
	void configStep3 (int index, UserCommand& aCommand);

	void performSearch (const SEARCH_STRUCT& searchInfo); 
	void sortEvents (vector<pos_int>& IDs);	
	void configuration ();
	
	void saveToFile ();
	void loadFromFile ();
	void displayAll();
};

typedef Operations * const WriteOperationPtr;
typedef Operations const * const ReadOperationPtr; 

static bool sortBySmallerTime (const SORT_STRUCT &a, const SORT_STRUCT &b){
	return a.startTime < b.startTime ;
}

static bool sortByLargerTime (const SORT_STRUCT &a, const SORT_STRUCT &b){
	return a.startTime > b.startTime ;
}

static bool compareByDescription (const SORT_STRUCT &a, const SORT_STRUCT &b){
	return a.description < b.description ;
}
